package com.example.interview.example.trafficLightSystem;

/**
 *   1.系统中有12个方向上的灯，在程序的其他地方要根据灯的名称就可以获得对应的灯的实例对象，综合这些因素，将Lamp类用java5中的枚举形式定义更为简单。
 *   2.每个Lamp对象中的亮黑状态用lighted变量表示，选用S2N、S2W、E2W、E2N这四个方向上的Lamp对象依次轮询变亮，Lamp对象中还要有一个oppositeLampName
 *      变量来表示它们相反方向的灯，再用一个nextLampName变量来表示此灯变亮后的下一个变亮的灯。这三个变量用构造方法的形式进行赋值，因为枚举元素
 *      必须在定义之后引用，所以无法再构造方法中彼此相互引用，所以，相反方向和下一个方向的灯用字符串形式表示。
 *   3.增加让Lamp变亮和变黑的方法：light和blackOut，对于S2N、S2W、E2W、E2N这四个方向上的Lamp对象，这两个方法内部要让相反方向的灯随之变亮和变黑，blackOut方法还要让下一个灯变亮。
 *   4.除了S2N、S2W、E2W、E2N这四个方向上的Lamp对象之外，其他方向上的Lamp对象的nextLampName和oppositeLampName属性设置为null即可，并且S2N、S2W、E2W、E2N
 *      这四个方向上的Lamp对象的nextLampName和oppositeLampName属性必须设置为null，以便防止light和blackOut进入死循环。
 *
 * 每个Lamp元素代表一个方向上的灯，总共有12个方向，所有总共有12个Lamp元素。
 * 有如下一些方向上的灯,每两个形成一组，一组灯同时变绿或变红，所以，
 * 程序代码只需要控制每组灯中的一个灯即可：
 * s2n,n2s
 * s2w,n2e
 * e2w,w2e
 * e2s,w2n
 * s2e,n2w
 * e2n,w2s
 * 上面最后两行的灯是虚拟的，由于从南向东和从西向北、以及它们的对应方向不受红绿灯的控制，
 * 所以，可以假想它们总是绿灯。
 *
 * @author 张孝祥 www.it315.org
 */
/**/
public enum Lamp {
    /*每个枚举元素各表示一个方向的控制灯*/
    S2N("N2S", "S2W", false), S2W("N2E", "E2W", false), E2W("W2E", "E2S", false), E2S("W2N", "S2N", false),
    /*下面元素表示与上面的元素的相反方向的灯，它们的“相反方向灯”和“下一个灯”应忽略不计！*/
    N2S(null, null, false),   N2E(null, null, false),   W2E(null, null, false),   W2N(null, null, false),
    /*由南向东、由西向北等右拐弯的灯不受红绿灯的控制，所以，可以假想它们总是绿灯*/
    S2E(null, null, true), E2N(null, null, true), N2W(null, null, true), W2S(null, null, true);

    private Lamp(String opposite, String next, boolean lighted) {
        this.opposite = opposite;
        this.next = next;
        this.lighted = lighted;
    }

    private boolean lighted;  /*当前灯是否为绿*/
    private String opposite;  /*与当前灯同时为绿的对应方向*/
    private String next;      /*当前灯变红时下一个变绿的灯*/

    public boolean isLighted() {
        return lighted;
    }

    //让灯变绿的方法(此灯变绿时，它对面方向的灯也要变绿)
    public void light() {
        this.lighted = true;
        if (opposite != null) {
            Lamp.valueOf(opposite).light();
        }
        System.out.println(name() + " lamp is green，6个方向有汽车通过(6个拐弯的方向)！");
    }

    /**
     * 让灯变红的方法(此灯变红时，对应方向的灯也要变红，并且下一个方向的灯要变绿)
     * @return 下一个要变绿的灯
     */
    public Lamp blackOut() {
        this.lighted = false;
        if (opposite != null) {
            Lamp.valueOf(opposite).blackOut();
        }
        Lamp nextLamp = null;
        if (next != null) {
            nextLamp = Lamp.valueOf(next);
            //                            this.opposite
            System.out.println("绿灯从" + this.name() + "-------->切换为" + this.next);//拐弯
            nextLamp.light();//下一个方向的灯要变绿
        }
        return nextLamp;
    }
}
